home *** CD-ROM | disk | FTP | other *** search
/ Night Owl 6 / Night Owl's Shareware - PDSI-006 - Night Owl Corp (1990).iso / 020a / giftoeps.zip / GIFTOPS.C < prev    next >
Text File  |  1990-07-12  |  15KB  |  478 lines

  1. /*********************************************
  2.  *             GIFtoPS Converter             *
  3.  *                                           *
  4.  *      May 16, 1988  by Scott Hemphill      *
  5.  *                                           *
  6.  * I wrote this program, and hereby place it *
  7.  * in the public domain, i.e. there are no   *
  8.  * copying restrictions of any kind.         *
  9.  *                         *
  10.  * Command line processing, EPSF support,    *
  11.  * and image positioning by Mic Kaczmarczik, *
  12.  * modeled after James Frew's ``suntops''    *
  13.  *                         *
  14.  * All ints were assumed 32 bits, changed to *
  15.  * work with 16 bit ints with mwc on Atari ST*
  16.  * The routine below provides the getopt()   *
  17.  * routine unavailable with mwc.             *
  18.  * A GEM version for the Atari ST may be     *
  19.  * appearing soon in the Atari SIG.          *
  20.  * Mark Storkamp 3/24/90.             *
  21.  *                                           *
  22.  * Converted to compile under Turbo C 2.0    *
  23.  * Changed "raster","fill", and "scanline"   *
  24.  * to HUGE pointers and compiled using       *
  25.  * "compact" memory model. Also stripped out *
  26.  * the getopt() function (for troubleshooting*
  27.  * purposes). Turbo C includes getopt() if   *
  28.  * you want it. Atof() were substituted for  *
  29.  * sscanf() in the command line parser (for  *
  30.  * getting imageheight and imagewidth values,*
  31.  * I was unable to get atof to work with my  *
  32.  * compiler).                                *
  33.  * Craig Moore 4/13/90                       *
  34.  *********************************************/
  35.  
  36. #include <stdlib.h>
  37. #include <stdio.h>
  38. #include <string.h>
  39. #include <alloc.h>
  40.  
  41.  
  42. #define FALSE 0
  43. #define TRUE 1
  44.  
  45. typedef int bool;
  46. typedef struct codestruct {
  47.             struct codestruct *prefix;
  48.             unsigned char first,suffix;
  49.         } codetype;
  50.  
  51.  
  52. FILE *infile;
  53. unsigned int screenwidth;           /* The dimensions of the screen */
  54. unsigned int screenheight;          /*   (not those of the image)   */
  55. bool global;                        /* Is there a global color map? */
  56. int globalbits;                     /* Number of bits of global colors */
  57. unsigned char globalmap[256][3];    /* RGB values for global color map */
  58. char colortable[256][3];            /* Hex intensity strings for an image */
  59. char huge *raster;              /* Decoded image data */
  60. codetype codetable[4096];                /* LZW compression code data */
  61. int datasize,codesize,codemask;     /* Decoder working variables */
  62. int clear,eoi;                      /* Special code values */
  63.  
  64. #define INCH  72.0
  65. int EPSF = FALSE;            /* should we generate EPSF?        */
  66. int screen = FALSE;                /* use alternate halftone screen?    */
  67. int landscape = FALSE;            /* display image in landscape mode? */
  68. int copies = 1;                /* number of copies to create    */
  69.  
  70. double pagewidth;
  71. double pageheight;
  72. double imagewidth;
  73. double imageheight;
  74.  
  75.  
  76. void usage()
  77. {
  78.     fprintf(stderr,
  79.    "usage: giftops [-els] [-c{copies}] [-w{width}] [-h{height}] [file]\n");
  80.     exit(-1);
  81. }
  82.  
  83. void fatal(s)
  84. char *s;
  85. {
  86.         fprintf(stderr,"giftops: %s\n",s);
  87.         exit(-1);
  88. }
  89.  
  90. void checksignature()
  91. {
  92.         char buf[6];
  93.  
  94.         fread(buf,1,6,infile);
  95.         if (strncmp(buf,"GIF",3)) fatal("file is not a GIF file");
  96.         if (strncmp(&buf[3],"87a",3)) fatal("unknown GIF version number");
  97. }
  98.  
  99. /* Get information which is global to all the images stored in the file */
  100.  
  101. void readscreen()
  102. {
  103.         unsigned char buf[7];
  104.  
  105.         fread(buf,1,7,infile);
  106.         screenwidth = buf[0] + (buf[1] << 8);
  107.         screenheight = buf[2] + (buf[3] << 8);
  108.         global = buf[4] & 0x80;
  109.         if (global) {
  110.             globalbits = (buf[4] & 0x07) + 1;
  111.             fread(globalmap,3,1<<globalbits,infile);
  112.         }
  113. }
  114.  
  115. /* Convert a color map (local or global) to an array of two character
  116.    hexadecimal strings, stored in colortable.  RGB is converted to
  117.    8-bit grayscale using integer arithmetic. */
  118.  
  119. void initcolors(colortable,colormap,ncolors)
  120. char colortable[256][3];
  121. unsigned char colormap[256][3];
  122. int ncolors;
  123. {
  124.         static char hextab[] = {'0','1','2','3','4','5','6','7',
  125.                                 '8','9','A','B','C','D','E','F'};
  126.         register unsigned color;
  127.         register i;
  128.  
  129.         for (i = 0; i < ncolors; i++) {
  130.             color = 77*colormap[i][0] + 150*colormap[i][1] + 29*colormap[i][2];
  131.             color >>= 8;
  132.             colortable[i][0] = hextab[color >> 4];
  133.             colortable[i][1] = hextab[color & 15];
  134.             colortable[i][2] = '\0';
  135.         }
  136. }
  137.  
  138. /* Write a postscript header to the standard output.
  139.  *
  140.  * imagewidth and imageheight always represent the width/height of the
  141.  * bounding box in the standard PostScript coordinate system, even when
  142.  * the image rotated 90 degrees.
  143.  */
  144.  
  145. void writeheader(left,top,width,height)
  146. unsigned left,top,width,height;
  147. {
  148.         double aspect, xorg, yorg;
  149.  
  150.     /*
  151.      * using imagewidth and imageheight as maxima, figure out how
  152.      * tall and wide the image will be on the PostScript page.
  153.      */
  154.     aspect = ((double) width) / ((double) height);
  155.     if (landscape) {
  156.         if (aspect >= imageheight / imagewidth)
  157.             imagewidth = imageheight / aspect;
  158.         else
  159.             imageheight = imagewidth * aspect;
  160.     } else {
  161.         if (aspect >= imagewidth / imageheight)
  162.             imageheight = imagewidth / aspect;
  163.         else
  164.             imagewidth = imageheight * aspect;
  165.     }
  166.  
  167.     /*
  168.      * For simplicity's sake, EPSF files have origin (0, 0).
  169.      */
  170.     if (EPSF) {
  171.         xorg = yorg = 0.0;
  172.         printf("%%!PS-Adobe-2.0 EPSF-1.2\n");    /* magic number */
  173.     } else {
  174.         xorg = (pagewidth - imagewidth) / 2.0;
  175.         yorg = (pageheight - imageheight) / 2.0;
  176.         printf("%%!\n");
  177.     }
  178.  
  179.     printf("%%%%BoundingBox: %.3f %.3f %.3f %.3f\n",
  180.            xorg, yorg, xorg + imagewidth, yorg + imageheight);
  181.     printf("%%%%Creator: GIFtoPS\n");
  182.     printf("%%%%EndComments\n");
  183.  
  184.     /*
  185.      * setting # of copies doesn't make sense if creating EPSF file
  186.      */
  187.     if (!EPSF)
  188.         printf("/#copies %d def\n", copies);
  189.     printf("gsave\n");
  190.     printf("/alternatehalftone %s def\n", screen ? "true" : "false");
  191.         printf("alternatehalftone {\n");
  192.     printf("   currentscreen\n");
  193.     printf("   /proc exch def /angle exch def /frequency exch def\n");
  194.         printf("   /angle 90 def /frequency 60 def\n");
  195.         printf("   frequency angle /proc load setscreen\n");
  196.     printf("} if\n");
  197.  
  198.         printf("/picstr %d string def\n",width);
  199.         printf("/screen {\n");
  200.     printf("   %d %d 8 [%d 0 0 -%d 0 %d]\n",
  201.            width, height, width, height, height);
  202.         printf("   {currentfile picstr readhexstring pop} image} def\n");
  203.         printf("%.3f %.3f translate\n", xorg, yorg);
  204.     if (landscape) {
  205.         printf("%.3f 0 translate 90 rotate %.3f %.3f scale\n",
  206.                imagewidth, imageheight, imagewidth);
  207.     } else {
  208.         printf("%.3f %.3f scale\n", imagewidth, imageheight);
  209.     }
  210.     printf("screen\n");
  211. }
  212.  
  213.  
  214. /* Output the bytes associated with a code to the raster array */
  215.  
  216. void outcode(p,fill)
  217. register codetype *p;
  218. register unsigned char (huge **fill);
  219. {
  220.         if (p->prefix) outcode(p->prefix,fill);
  221.         *(*fill)++ = p->suffix;
  222. }
  223.  
  224. /* Process a compression code.  "clear" resets the code table.  Otherwise
  225.    make a new code table entry, and output the bytes associated with the
  226.    code. */
  227.  
  228. void process(code,fill)
  229. register code;
  230. unsigned char (huge **fill);
  231. {
  232.         static avail,oldcode;
  233.         register codetype *p;
  234.  
  235.         if (code == clear) {
  236.             codesize = datasize + 1;
  237.             codemask = (1 << codesize) - 1;
  238.             avail = clear + 2;
  239.             oldcode = -1;
  240.         } else if (code < avail) {
  241.             outcode(&codetable[code],fill);
  242.             if (oldcode != -1) {
  243.                 p = &codetable[avail++];
  244.                 p->prefix = &codetable[oldcode];
  245.                 p->first = p->prefix->first;
  246.                 p->suffix = codetable[code].first;
  247.                 if ((avail & codemask) == 0 && avail < 4096) {
  248.                     codesize++;
  249.                     codemask += avail;
  250.                 }
  251.             }
  252.             oldcode = code;
  253.         } else if (code == avail && oldcode != -1) {
  254.             p = &codetable[avail++];
  255.             p->prefix = &codetable[oldcode];
  256.             p->first = p->prefix->first;
  257.             p->suffix = p->first;
  258.             outcode(p,fill);
  259.             if ((avail & codemask) == 0 && avail < 4096) {
  260.                 codesize++;
  261.                 codemask += avail;
  262.             }
  263.             oldcode = code;
  264.         } else {
  265.             fatal("illegal code in raster data");
  266.         }
  267. }
  268.  
  269. /* Decode a raster image */
  270.  
  271. void readraster(width,height)
  272. unsigned width,height;
  273. {
  274.     unsigned char huge *fill = raster;
  275.         unsigned char buf[255];
  276.         register bits=0;
  277.         register unsigned count;
  278.     register unsigned long datum=0L;
  279.         register unsigned char *ch;
  280.         register int code;
  281.  
  282.         datasize = getc(infile);
  283.         clear = 1 << datasize;
  284.         eoi = clear+1;
  285.         codesize = datasize + 1;
  286.         codemask = (1 << codesize) - 1;
  287.         for (code = 0; code < clear; code++) {
  288.             codetable[code].prefix = (codetype*)0;
  289.             codetable[code].first = code;
  290.             codetable[code].suffix = code;
  291.         }
  292.         for (count = getc(infile); count > 0; count = getc(infile)) {
  293.             fread(buf,1,count,infile);
  294.             for (ch=buf; count-- > 0; ch++) {
  295.         datum += (long)*ch << bits;
  296.                 bits += 8;
  297.                 while (bits >= codesize) {
  298.             code = datum & codemask;
  299.                     datum >>= codesize;
  300.                     bits -= codesize;
  301.                     if (code == eoi) goto exitloop;  /* This kludge put in
  302.                                                         because some GIF files
  303.                                                         aren't standard */
  304.                     process(code,&fill);
  305.                 }
  306.             }
  307.         }
  308. exitloop:
  309.         if (fill != raster + (long)width*height) fatal("raster has the wrong size");
  310. }
  311.  
  312. /* Read a row out of the raster image and write it to the output file */
  313.  
  314. void rasterize(row,width)
  315. int row,width;
  316. {
  317.     unsigned char (huge *scanline);
  318.         register i;
  319.  
  320.        scanline = raster + (long)row*width;
  321.         for (i = 0; i < width; i++) {
  322.             if (i % 40 == 0) printf("\n");  /* break line every 80 chars */
  323.             fputs(colortable[*scanline++],stdout);
  324.         }
  325.         printf("\n");
  326. }
  327.  
  328. /* write image trailer to standard output */
  329.  
  330. void writetrailer()
  331. {
  332.     printf("\n\ngrestore\n");
  333.     if (!EPSF)
  334.         printf("showpage\n");
  335. }
  336.  
  337. /* Read image information (position, size, local color map, etc.) and convert
  338.    to postscript. */
  339.  
  340. void readimage()
  341. {
  342.         unsigned char buf[9];
  343.         unsigned left,top,width,height;
  344.     unsigned long lwidth, lheight;
  345.         bool local,interleaved;
  346.         char localmap[256][3];
  347.         int localbits;
  348.         int *interleavetable;
  349.         register row;
  350.         register i;
  351.  
  352.         fread(buf,1,9,infile);
  353.         left = buf[0] + (buf[1] << 8);
  354.         top = buf[2] + (buf[3] << 8);
  355.         lwidth = width = buf[4] + (buf[5] << 8);
  356.         lheight = height = buf[6] + (buf[7] << 8);
  357.         local = buf[8] & 0x80;
  358.         interleaved = buf[8] & 0x40;
  359.         if (local) {
  360.             localbits = (buf[8] & 0x7) + 1;
  361.             fread(localmap,3,1<<localbits,infile);
  362.             initcolors(colortable,localmap,1<<localbits);
  363.         } else if (global) {
  364.             initcolors(colortable,globalmap,1<<globalbits);
  365.         } else {
  366.             fatal("no colormap present for image");
  367.         }
  368.     writeheader(left,top,width,height);
  369.     raster = (char huge *)farmalloc(lwidth*lheight);
  370.         if (!raster) fatal("not enough memory for image");
  371.         readraster(width,height);
  372.         if (interleaved) {
  373.             interleavetable = (int*)malloc(lheight*sizeof(int));
  374.             if (!interleavetable) fatal("not enough memory for interleave table");
  375.             row = 0;
  376.             for (i = top; i < top+height; i += 8) interleavetable[i] = row++;
  377.             for (i = top+4; i < top+height; i += 8) interleavetable[i] = row++;
  378.             for (i = top+2; i < top+height; i += 4) interleavetable[i] = row++;
  379.             for (i = top+1; i < top+height; i += 2) interleavetable[i] = row++;
  380.             for (row = top; row < top+height; row++) rasterize(interleavetable[row],width);
  381.             free(interleavetable);
  382.         } else {
  383.             for (row = top; row < top+height; row++) rasterize(row,width);
  384.         }
  385.     farfree(raster);
  386.         writetrailer();
  387. }
  388.  
  389. /* Read a GIF extension block (and do nothing with it). */
  390.  
  391. void readextension()
  392. {
  393.         unsigned char code,count;
  394.         char buf[255];
  395.  
  396.         code = getc(infile);
  397.         while (count = getc(infile)) fread(buf,1,count,infile);
  398. }
  399.  
  400. extern char    *optarg;
  401. extern int      optind;
  402.  
  403. main(argc,argv)
  404. int argc;
  405. char *argv[];
  406. {
  407.         int quit = FALSE;
  408.         int opt, posn = 0;
  409.     char ch, gifname[40];
  410.     char optarg[10];
  411.  
  412.     pagewidth = 8.5 * INCH;        /* width, height of PostScript page    */
  413.     pageheight = 11.0 * INCH;
  414.     imagewidth = 7.5 * INCH;    /* default max image height        */
  415.     imageheight = 9.0 * INCH;
  416.  
  417.     while((++posn < argc) && (argv[posn][0] == '-')){
  418.             opt = argv[posn][1];
  419.             if(strlen(argv[posn]) > 2) strcpy(optarg, argv[posn]+2);
  420.  
  421.  
  422.         switch (opt) {
  423.         case 'c':
  424.             if ((copies = atoi(optarg)) <= 0)
  425.                 fatal("#copies must be > 0");
  426.             break;
  427.         case 'e':
  428.             EPSF = TRUE;
  429.             break;
  430.         case 'l':
  431.             landscape = TRUE;
  432.             break;
  433.         case 's':
  434.             screen = TRUE;
  435.             break;
  436.         case 'w':
  437.         sscanf(optarg,"%lf",&imagewidth);
  438.             imagewidth *= INCH;
  439.             if (imagewidth <= 0.0)
  440.                 fatal("negative image width");
  441.             break;
  442.         case 'h':
  443.          sscanf(optarg,"%lf",&imageheight);
  444.             imageheight *= INCH;
  445.             if (imageheight <= 0.0)
  446.                 fatal("negative image height");
  447.             break;
  448.         default:
  449.             usage();
  450.             break;
  451.         }
  452.     }
  453.         strcpy(gifname, argv[posn]);
  454.         infile = fopen(gifname,"rb");
  455.         if (infile == NULL) {
  456.             perror("giftops");
  457.             exit(-1);
  458.         }
  459.  
  460.  
  461.         checksignature();
  462.         readscreen();
  463.         do {
  464.             ch = getc(infile);
  465.             switch (ch) {
  466.                 case '\0':  break;  /* this kludge for non-standard files */
  467.                 case ',':   readimage();
  468.                             break;
  469.                 case ';':   quit = TRUE;
  470.                             break;
  471.                 case '!':   readextension();
  472.                             break;
  473.                 default:    fatal("illegal GIF block type");
  474.                             break;
  475.             }
  476.         } while (!quit);
  477. }
  478.